#include <QtTest>
#include <QDebug>
//#include <QtWidgets>
#include <QLineEdit>
#include <QMessageBox>
#include <QInputDialog>

// add necessary includes here

class testclass1 : public QObject
{
    Q_OBJECT

public:
    testclass1();
    ~testclass1();

private slots:  // 在private slots下的都是测试用例

    /**
     * @brief initTestCase,所有的测试用例执行前都执行的特殊初始化测试函数
     */
    void initTestCase();

    /**
     * @brief cleanupTestCase  所有的测试用例都执行完毕才执行的特殊清理测试函数
     */
    void cleanupTestCase();

    /**
     * @brief init  每个测试用例测试前都调用的特殊初始化测试函数
     */
    void init();

    /**
     * @brief cleanup  每个测试用例测试前都调用的特殊清理测试函数
     */
    void cleanup();

    /**
     * @brief test_case1  自定义测试用例
     */
    void test_case1();


    void test_case2();

    /**
     * @brief testcase3_data  测试函数以 xxx_data结层是测试函数xxx的数据准备函数，比xxx()函数先执行，数据准备函数前后没有init cleanup
     */
    void testcase3_data();
    void testcase3();


    /**
     * @brief testGui_data  指量创建gui事件
     */
    void testGui_data();
    /**
     * @brief testGui   GUI测试示例
     */
    void testGui();

    /**
     * @brief testBenchmark 执行性能测试
     */
    void testBenchmark();

};

testclass1::testclass1()
{

}

testclass1::~testclass1()
{

}

void testclass1::initTestCase()
{
//    QWARN("initTestCase函数被执行!");
    qDebug()<<__FUNCTION__"函数被执行!";
}

void testclass1::cleanupTestCase()
{
//    QWARN("cleanupTestCase函数被执行!");
    qDebug()<<__FUNCTION__"函数被执行!";
}

void testclass1::init()
{
//    QWARN("init函数被执行!");
    qDebug()<<__FUNCTION__"函数被执行!";
}

void testclass1::cleanup()
{
//    QWARN("cleanup函数被执行!");
    qDebug()<<__FUNCTION__"函数被执行!";
}

void testclass1::test_case1()
{
    QVERIFY(true);  // 测试是否为true
    QCOMPARE(1,1);  // 测试是否相等
    qDebug()<<__FUNCTION__"函数被执行!";
}

void testclass1::test_case2()
{
    qDebug()<<__FUNCTION__"函数被执行!";
    QVERIFY(true);  // 测试是否为true
}

void testclass1::testcase3_data()
{
    qDebug()<<__FUNCTION__"函数被执行!";
    QTest::addColumn<QString>("string");    //给数据结构表增加两个列，分别为 string,result
    QTest::addColumn<QString>("result");

    QTest::newRow("all lower") << "hello" << "HELLO";  //给数据结构表增加三行数据
    QTest::newRow("mixed")     << "Hello" << "HELLO";
    QTest::newRow("all upper") << "HELLO" << "HELLO";
}

void testclass1::testcase3()
{
    qDebug()<<__FUNCTION__"函数被执行!";

    QFETCH(QString, string);    //从数据结构表获取string列的数据用于测试
    QFETCH(QString, result);    //从数据结构表获取result列的数据用于测试
    QCOMPARE(string.toUpper(), result); //由于数据表里有等待数据，所以testcase3执行了三次且每次都有 init() cleanup()
}

void testclass1::testGui_data()
{
    QTest::addColumn<QTestEventList>("events");
    QTest::addColumn<QString>("expected");
    QTest::addColumn<QString>("description");

    QTestEventList list1;
    list1.addKeyClick('a');
    QTest::newRow("char") << list1 << "a" << "第一次事件列表仅输入字符'a'";

    QTestEventList list2;
    list2.addKeyClick('a');
    list2.addKeyClick(Qt::Key_Backspace);
    QTest::newRow("there and back again") << list2 << "" << "第二次事件列表输入字符'a'后输入退格";
}

void testclass1::testGui()
{
    if(QMessageBox(QMessageBox::Icon::Question,
                "跳过","要跳过测试不？",
                QMessageBox::Yes | QMessageBox::No
                ).exec() == QMessageBox::Yes){
        QSKIP("你选择跳过测试");   // QSKIP在数据驱动的测试函数中每次调用仅跳过一次数据，如果在以_data结尾的准备数据函数中它会跳过相对应的整个测试函数执行
    }

    QLineEdit lineEdit;
    lineEdit.show();
//    QTest::keyClicks(&lineEdit, "hello world"); // 模拟键盘事件，还有很多其它的函数
//    QCOMPARE(lineEdit.text(), QString("hello world"));

    QFETCH(QTestEventList, events);
    QFETCH(QString, expected);
    QFETCH(QString, description);

    //         QLineEdit lineEdit;
    events.simulate(&lineEdit);
    QCOMPARE(lineEdit.text(), expected);

    QMessageBox msgbox(
                QMessageBox::Icon::Question,
                "能看到GUI吗？",description + ",响应正常不？",
                QMessageBox::Yes | QMessageBox::No
                );

    QCOMPARE(msgbox.exec(),QMessageBox::Yes);
}

void testclass1::testBenchmark()
{
    qDebug()<<__FUNCTION__"函数被执行!";
    QString str1 = QLatin1String("This is a test string");
    QString str2 = QLatin1String("This is a test string");

    QCOMPARE(str1.localeAwareCompare(str2), 0);

    QBENCHMARK {            // QBENCHMARK默认是多次循环来测试执行时间的，它有其它非循环执行测试的选项
        str1.localeAwareCompare(str2);      //大括号内的代码会被测试运行时间
    }
}

/**
 * 如果要一个测试工程执行多个测试类，不使用QTEST_APPLESS_MAIN或QTEST_MAIN
 * 而是要创建一个main()函数，多测调用QTest::qExec()函数执行测试类，具体请参考QTEST_APPLESS_MAIN的宏实现，然后测试类最好头文件和源码文件分开写
 *
 */
QTEST_MAIN(testclass1)   //可单独执行的测试都应该加这个，相当于自动写main(),QTEST_APPLESS_MAIN是无gui的，QTEST_MAIN是带gui的


#include "tst_case1.moc"    //头文件和源文件不分开的测试类都应该加这个
